home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / program / libkb100.zip / LIBKB-1.00 / SRC / KBHANDLE.C < prev    next >
C/C++ Source or Header  |  1996-07-23  |  12KB  |  567 lines

  1. /* kbhandle.c -- MSDOS keyboard interrupt handler / Linux keyboard handler
  2.  * Copyright (C) 1995, 1996 Markus F.X.J. Oberhumer
  3.  * For conditions of distribution and use, see copyright notice in kb.h 
  4.  */
  5.  
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <signal.h>
  10. #include <string.h>
  11. #include <limits.h>
  12.  
  13. #include <kb.h>
  14. #include "_kb.h"
  15.  
  16.  
  17. #if defined(KB_LOCK_ALL_START)
  18. KB_LOCK_ALL_START(_libkb_kbhandle)
  19. #endif
  20.  
  21.  
  22. #if defined(__KB_MSDOS)
  23. #  define KB_ACKINT()        KB_OUTP8(0x20, 0x20)    /* ack. interrupt */
  24. #else
  25. #  define KB_ACKINT()        /* no interrupt */
  26. #endif
  27.  
  28.  
  29. /***********************************************************************
  30. // globals
  31. ************************************************************************/
  32.  
  33. volatile unsigned char _kb_key[128];        /* the key flags */
  34. volatile unsigned short _kb_shift = 0;        /* shift state */
  35. volatile int _kb_keys_pressed = 0;            /* number of keys pressed */
  36. volatile unsigned short _kb_last_key = 0;    /* last key pressed */
  37.  
  38. int _kb_mode = 0;                        /* do we have a keyboard handler? */
  39. unsigned long _kb_flags = 0;            /* flags from kb_install() */
  40.  
  41. kb_handler_callback_t kb_handler_callback = NULL;
  42.  
  43.  
  44. /***********************************************************************
  45. // static variables
  46. // These are not volatile because all access outside the
  47. //   interrupt handler uses KB_DISABLE().
  48. ************************************************************************/
  49.  
  50. static unsigned char _t_prefix = 0;
  51. static char _emergency_done = 0;    /* don't recurse here */
  52.  
  53. #define KEY_BUFFER_SIZE 256        /* store up to 256 keys for kb_keypress() */
  54.  
  55. static unsigned char _key_buffer[2*KEY_BUFFER_SIZE];
  56. #define _key_buffer_start    (&_key_buffer[0])
  57. #define _key_buffer_end        (&_key_buffer[HIGH(_key_buffer)])
  58.  
  59. static unsigned char *_key_buffer_head = _key_buffer_start;
  60. static unsigned char *_key_buffer_tail = _key_buffer_start;
  61.  
  62.  
  63. /* debugging and error reporting */
  64.  
  65. #if defined(KB_DEBUG)
  66. static unsigned char _kb_port_buffer[128];
  67. #define _kb_port_buffer_start    (&_kb_port_buffer[0])
  68. #define _kb_port_buffer_end        (&_kb_port_buffer[sizeof(_kb_port_buffer)])
  69. static unsigned char *_kb_port_buffer_head = _kb_port_buffer_start;
  70. #endif
  71.  
  72. /* I've just (07 Jan 1996) taken a look at the Linux kernel source
  73.  * and come to the conclusion that reporting all unknown scan-codes
  74.  * as a bug is probably counterproductive.
  75.  * It seems that there exist lots of keyboards that produce lots 
  76.  * of codes we are simply not interested in.
  77.  * I have removed all error reporting, the port values give us
  78.  * enough information if we want to add something new.
  79.  */
  80.  
  81.  
  82. /***********************************************************************
  83. // reset all vars except _kb_flags
  84. ************************************************************************/
  85.  
  86. static void _kb_clear(void)
  87. {
  88.     KB_DISABLE();
  89.     memset((void *)_kb_key,0,sizeof(_kb_key));    /* cast away volatile */
  90.     _kb_shift = 0;
  91.     _kb_keys_pressed = 0;
  92.     _kb_last_key = 0;
  93.     kb_handler_callback = 0;
  94.  
  95.     _t_prefix = 0;
  96.  
  97.     _key_buffer_head = _key_buffer_tail = _key_buffer_start;
  98.     KB_ENABLE();
  99. }
  100.  
  101.  
  102. /***********************************************************************
  103. //
  104. ************************************************************************/
  105.  
  106. int kb_kbhit()
  107. {
  108.     int c;
  109.  
  110.     if (!_kb_mode)
  111.         return kb_os_kbhit();
  112.  
  113.     kb_update();
  114.     KB_DISABLE();
  115.     c = (_key_buffer_head != _key_buffer_tail);
  116.     KB_ENABLE();
  117.  
  118.     return c;
  119. }
  120.  
  121. int kb_kbhit_i()
  122. {
  123.     if (!_kb_mode)
  124.         return kb_os_kbhit();
  125.     kb_update();
  126.     return (_key_buffer_head != _key_buffer_tail);
  127. }
  128.  
  129.  
  130. void kb_clearkeys(void)
  131. {
  132.     kb_update();
  133.     KB_DISABLE();
  134.     _key_buffer_tail = _key_buffer_head;
  135.     KB_ENABLE();
  136. }
  137.  
  138. void kb_clearkeys_i(void)
  139. {
  140.     kb_update();
  141.     _key_buffer_tail = _key_buffer_head;
  142. }
  143.  
  144.  
  145. /***********************************************************************
  146. // basic keypress access.
  147. // this function returns all relevant information:
  148. //   the scancode and the low bits of the shift status
  149. // kb_getkey() and kb_inkey() sit on top of this function.
  150. ************************************************************************/
  151.  
  152. unsigned kb_keypress(void)
  153. {
  154.     unsigned char scan, shift;
  155.     unsigned k;
  156.  
  157.     if (!_kb_mode)
  158.         return 0;
  159.  
  160.     kb_update();
  161.  
  162.     KB_DISABLE();
  163.     if (_key_buffer_head == _key_buffer_tail)
  164.     {
  165.         KB_ENABLE();
  166.         return 0;
  167.     }
  168.  
  169.     scan = *_key_buffer_tail++;                /* get scan code */
  170.     shift = *_key_buffer_tail++;            /* get shift code */
  171.     if (_key_buffer_tail >= _key_buffer_end)
  172.         _key_buffer_tail = _key_buffer_start;
  173.     KB_ENABLE();
  174.  
  175.     k = scan | ((unsigned) shift << 8);
  176.     return k;
  177. }
  178.  
  179.  
  180. unsigned kb_keypress_i(void)
  181. {
  182.     unsigned char scan, shift;
  183.     unsigned k;
  184.  
  185.     if (!_kb_mode)
  186.         return 0;
  187.  
  188.     kb_update();
  189.  
  190.     if (_key_buffer_head == _key_buffer_tail)
  191.         return 0;
  192.     scan = *_key_buffer_tail++;                /* get scan code */
  193.     shift = *_key_buffer_tail++;            /* get shift code */
  194.     if (_key_buffer_tail >= _key_buffer_end)
  195.         _key_buffer_tail = _key_buffer_start;
  196.  
  197.     k = scan | ((unsigned) shift << 8);
  198.     return k;
  199. }
  200.  
  201.  
  202. unsigned kb_keypeek(void)
  203. {
  204.     unsigned char scan, shift;
  205.     unsigned k;
  206.  
  207.     if (!_kb_mode)
  208.         return 0;
  209.  
  210.     kb_update();
  211.  
  212.     KB_DISABLE();
  213.     if (_key_buffer_head == _key_buffer_tail)
  214.     {
  215.         KB_ENABLE();
  216.         return 0;
  217.     }
  218.  
  219.     scan = *_key_buffer_tail;                /* get scan code */
  220.     shift = *(_key_buffer_tail+1);            /* get shift code */
  221.     KB_ENABLE();
  222.  
  223.     k = scan | ((unsigned) shift << 8);
  224.     return k;
  225. }
  226.  
  227.  
  228. unsigned kb_keypeek_i(void)
  229. {
  230.     unsigned char scan, shift;
  231.     unsigned k;
  232.  
  233.     if (!_kb_mode)
  234.         return 0;
  235.  
  236.     kb_update();
  237.  
  238.     if (_key_buffer_head == _key_buffer_tail)
  239.         return 0;
  240.     scan = *_key_buffer_tail;                /* get scan code */
  241.     shift = *(_key_buffer_tail+1);            /* get shift code */
  242.  
  243.     k = scan | ((unsigned) shift << 8);
  244.     return k;
  245. }
  246.  
  247.  
  248. /***********************************************************************
  249. // low level stuff
  250. ************************************************************************/
  251.  
  252. #if defined(__KB_MSDOS)
  253. #  include "_kbmsdos.h"
  254. #elif defined(__KB_LINUX)
  255. #  include "_kblinux.h"
  256. #endif
  257.  
  258.  
  259. /***********************************************************************
  260. // high level installation
  261. ************************************************************************/
  262.  
  263. int kb_init(void)
  264. {
  265.     _kb_init_tables();
  266.     if (!_kb_mode)
  267.         _kb_clear();
  268.     return 0;
  269. }
  270.  
  271.  
  272. int kb_install(unsigned long flags)
  273. {
  274.     if (_kb_mode)
  275.         return 0;
  276.  
  277.     _kb_flags = flags;
  278.     _kb_flags &= 0xffff;
  279. #if defined(KB_DEBUG)
  280.     fprintf(stderr,"kb_install 1: 0x%08lx\n", _kb_flags);
  281. #endif
  282.  
  283.     if (!(_kb_flags & KB_FLAG_NO_ATEXIT))
  284.     {
  285.         static unsigned char atexit_done = 0;
  286.  
  287.         if (atexit_done)
  288.             _kb_flags |= KB_FLAG_ATEXIT_DONE;
  289.         else if (atexit(kb_remove) == 0)
  290.         {
  291.             _kb_flags |= KB_FLAG_ATEXIT_DONE;
  292.             atexit_done = 1;
  293.         }
  294.         else
  295.             _kb_flags |= KB_FLAG_ATEXIT_FAILED;
  296.     }
  297.  
  298.     if (!(_kb_flags & KB_FLAG_NO_LOCK))
  299.         if (_kb_lock() == 0)
  300.             _kb_flags |= KB_FLAG_LOCK_DONE;
  301.         else
  302.             _kb_flags |= KB_FLAG_LOCK_FAILED;
  303.  
  304.     /* link version information into executeable */
  305.     _kb_shift |= (kb_version_string[0] & kb_version_date[0] & kb_copyright[0]);
  306.     kb_init();
  307.     KB_DISABLE();
  308.     if (_kb_install() == 0)
  309.         _kb_mode = 1;
  310.     KB_ENABLE();
  311.  
  312. #if !defined(_KB_NO_SIGNALS)
  313.     /* install signals only if handler could be installed */
  314.     if (_kb_mode)
  315.         if (!(_kb_flags & KB_FLAG_NO_SIGNAL))
  316.             if (_kb_signal_install() == 0)
  317.                 _kb_flags |= KB_FLAG_SIGNAL_DONE;
  318.             else
  319.                 _kb_flags |= KB_FLAG_SIGNAL_FAILED;
  320. #endif
  321.  
  322. #if !defined(_KB_NO_SIGNALS) && defined(SIGALRM)
  323.     if (_kb_mode)
  324.         if (_kb_flags & KB_FLAG_EMERGENCY_SIGALRM)
  325.             if (_kb_signal_alarm_install() != 0)
  326.                 _kb_flags &= ~(KB_FLAG_EMERGENCY_SIGALRM);    /* failed */
  327. #else
  328.     _kb_flags &= ~(KB_FLAG_EMERGENCY_SIGALRM);
  329. #endif
  330.  
  331.  
  332. #if defined(KB_DEBUG)
  333.     fflush(stdout);
  334.     fprintf(stderr,"kb_install 2: 0x%08lx, %s\n", _kb_flags,
  335.             _kb_mode ? "ok" : "FAILED");
  336.     fflush(stderr);
  337. #endif
  338.  
  339.     return _kb_mode ? 0 : -1;
  340. }
  341.  
  342.  
  343. /***********************************************************************
  344. // high level removal
  345. ************************************************************************/
  346.  
  347. typedef void (*kb_cleanup_t)(void);
  348. static kb_cleanup_t
  349.     kb_cleanup_func1 = NULL,
  350.     kb_cleanup_func2 = NULL;
  351. static kb_cleanup_t
  352.     kb_emergency_cleanup_func1 = NULL,
  353.     kb_emergency_cleanup_func2 = NULL;
  354.  
  355. void kb_set_cleanup( void (*before)(void), void (*after)(void) )
  356. {
  357.     kb_cleanup_func1 = before;
  358.     kb_cleanup_func2 = after;
  359. }